#include <winsock2.h>
#include <mswsock.h> // For AcceptEx
#include <windows.h>
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <map>

// 定义一些常量
const int MAX_BUFFER_SIZE = 4096;
const int MAX_WORKER_THREADS = 4; // 可以根据CPU核心数调整

// 定义I/O操作类型
enum IO_OPERATION_TYPE
{
    IO_ACCEPT,
    IO_RECV,
    IO_SEND
};

// 每个客户端连接的数据结构
// 存储在CreateIoCompletionPort关联的句柄数据中
struct PER_HANDLE_DATA
{
    SOCKET ClientSocket;
    SOCKADDR_STORAGE ClientAddr;
    int ClientAddrLen;
};

// 每个I/O操作的数据结构
// 存储在OVERLAPPED结构体中
struct PER_IO_DATA
{
    OVERLAPPED Overlapped;
    WSABUF DataBuf;
    char Buffer[MAX_BUFFER_SIZE];
    IO_OPERATION_TYPE OperationType;
    SOCKET ClientSocketToAccept; // <--- ADD THIS
};

// 全局变量
HANDLE g_hCompletionPort;
SOCKET g_ListenSocket;
std::vector<std::thread> g_WorkerThreads;
std::mutex g_ClientMapMutex;
std::map<SOCKET, std::unique_ptr<PER_HANDLE_DATA>> g_ClientMap; // 管理客户端连接数据

// 函数声明
void WorkerThread(int threadId);
void HandleAccept(PER_HANDLE_DATA* pPerHandleData, PER_IO_DATA* pPerIoData);
void HandleRecv(PER_HANDLE_DATA* pPerHandleData, PER_IO_DATA* pPerIoData, DWORD dwBytesTransferred);
void HandleSend(PER_HANDLE_DATA* pPerHandleData, PER_IO_DATA* pPerIoData, DWORD dwBytesTransferred);
void CleanupClient(SOCKET clientSocket);

// 获取本地 AcceptEx 函数指针
LPFN_ACCEPTEX lpfnAcceptEx = NULL;
LPFN_GETACCEPTEXSOCKADDRS lpfnGetAcceptExSockaddrs = NULL;

void GetAcceptExFunctionPointers()
{
    GUID guidAcceptEx = WSAID_ACCEPTEX;
    DWORD dwBytes = 0;
    WSAIoctl(g_ListenSocket, SIO_GET_EXTENSION_FUNCTION_POINTER,
        &guidAcceptEx, sizeof(GUID),
        &lpfnAcceptEx, sizeof(LPFN_ACCEPTEX),
        &dwBytes, NULL, NULL);

    GUID guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
    WSAIoctl(g_ListenSocket, SIO_GET_EXTENSION_FUNCTION_POINTER,
        &guidGetAcceptExSockaddrs, sizeof(GUID),
        &lpfnGetAcceptExSockaddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS),
        &dwBytes, NULL, NULL);

    if (lpfnAcceptEx == NULL || lpfnGetAcceptExSockaddrs == NULL)
    {
        std::cerr << "Failed to get AcceptEx function pointers. Error: " << WSAGetLastError() << std::endl;
        exit(1);
    }
}

int main()
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        std::cerr << "WSAStartup failed. Error: " << WSAGetLastError() << std::endl;
        return 1;
    }

    // 1. 创建完成端口
    g_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
    if (g_hCompletionPort == NULL)
    {
        std::cerr << "CreateIoCompletionPort failed. Error: " << GetLastError() << std::endl;
        WSACleanup();
        return 1;
    }

    // 2. 创建监听套接字
    g_ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (g_ListenSocket == INVALID_SOCKET)
    {
        std::cerr << "WSASocket failed. Error: " << WSAGetLastError() << std::endl;
        CloseHandle(g_hCompletionPort);
        WSACleanup();
        return 1;
    }

    // 绑定监听套接字到完成端口
    if (CreateIoCompletionPort((HANDLE)g_ListenSocket, g_hCompletionPort, (ULONG_PTR)NULL, 0) == NULL)
    {
        std::cerr << "CreateIoCompletionPort for listen socket failed. Error: " << GetLastError() << std::endl;
        closesocket(g_ListenSocket);
        CloseHandle(g_hCompletionPort);
        WSACleanup();
        return 1;
    }

    // 绑定地址
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8888); // 监听端口
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网卡

    if (bind(g_ListenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
    {
        std::cerr << "bind failed. Error: " << WSAGetLastError() << std::endl;
        closesocket(g_ListenSocket);
        CloseHandle(g_hCompletionPort);
        WSACleanup();
        return 1;
    }

    // 监听
    if (listen(g_ListenSocket, SOMAXCONN) == SOCKET_ERROR)
    {
        std::cerr << "listen failed. Error: " << WSAGetLastError() << std::endl;
        closesocket(g_ListenSocket);
        CloseHandle(g_hCompletionPort);
        WSACleanup();
        return 1;
    }

    // 获取 AcceptEx 函数指针
    GetAcceptExFunctionPointers();

    std::cout << "Server listening on port 8888..." << std::endl;

    // 3. 启动工作线程
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    int numWorkerThreads = sysInfo.dwNumberOfProcessors * 2; // 通常是CPU核心数的两倍
    if (numWorkerThreads > MAX_WORKER_THREADS)
        numWorkerThreads = MAX_WORKER_THREADS;

    for (int i = 0; i < numWorkerThreads; ++i)
    {
        g_WorkerThreads.emplace_back(WorkerThread, i);
    }

    // 4. 投递初始的 AcceptEx 请求
    // 投递多个AcceptEx请求以提高并发接受能力
    for (int i = 0; i < numWorkerThreads * 2; ++i) // 投递多于工作线程数的AcceptEx
    {
        std::cout << "...............\n";
        PER_IO_DATA* pPerIoData = new PER_IO_DATA();
        ZeroMemory(&pPerIoData->Overlapped, sizeof(OVERLAPPED));
        pPerIoData->OperationType = IO_ACCEPT;   
        pPerIoData->DataBuf.buf = pPerIoData->Buffer;
        pPerIoData->DataBuf.len = 0; // No data buffer needed for AcceptEx


        // 为 AcceptEx 创建一个新的客户端套接字
        // For AcceptEx, you need a *new* clientSocket.
        // It's crucial that this socket is not yet associated with the completion port.
        SOCKET clientSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
        if (clientSocket == INVALID_SOCKET)
        {
            std::cerr << "WSASocket for AcceptEx failed. Error: " << WSAGetLastError() << std::endl;
            delete pPerIoData;
            continue;
        }
        std::cout << "clientSocket new success.\n";

        // 创建 PER_HANDLE_DATA
        // PER_HANDLE_DATA* pPerHandleData = new PER_HANDLE_DATA();
        // pPerHandleData->ClientSocket = clientSocket;
        pPerIoData->ClientSocketToAccept = clientSocket;

        DWORD dwBytesReceived = 0;
        // AcceptEx 的缓冲区需要足够大以包含本地和远程地址信息
        // AcceptEx 的地址缓冲区大小 = sizeof(sockaddr_storage) * 2 + 16
        // 16 是 AcceptEx 要求的额外字节
        ZeroMemory(pPerIoData->Buffer, sizeof(pPerIoData->Buffer)); // 清空缓冲区

        // When AcceptEx completes, pPerIoData->Overlapped will be returned.
        // The CompletionKey for the *listener socket* is NULL,
        // so pPerHandleData in WorkerThread will be NULL for IO_ACCEPT completions.
        if (!lpfnAcceptEx(g_ListenSocket, clientSocket,
            pPerIoData->Buffer, // 用于接收地址信息的缓冲区
            0, // 不接收数据，只接收地址信息
            sizeof(SOCKADDR_STORAGE) + 16,
            sizeof(SOCKADDR_STORAGE) + 16,
            &dwBytesReceived, &pPerIoData->Overlapped))
        {
            if (WSAGetLastError() != ERROR_IO_PENDING)
            {
                std::cerr << "AcceptEx failed. Error: " << WSAGetLastError() << std::endl;
                closesocket(clientSocket);
                // delete pPerHandleData;
                delete pPerIoData;
                continue;
            }
        }
    }


    // 等待工作线程结束（这里只是一个简单的阻塞，实际应用中会有更好的退出机制）
    for (auto& t : g_WorkerThreads)
    {
        t.join();
    }

    // 清理资源
    closesocket(g_ListenSocket);
    CloseHandle(g_hCompletionPort);
    WSACleanup();

    return 0;
}
std::mutex g_ConsoleMutex;

// 工作线程函数
void WorkerThread(int threadId)
{
    {
        std::lock_guard<std::mutex> lock(g_ConsoleMutex);
        std::cout << "Worker Thread " << threadId << " started." << std::endl;
    }

    DWORD dwBytesTransferred = 0;
    PER_HANDLE_DATA* pPerHandleData = NULL;
    PER_IO_DATA* pPerIoData = NULL;

    while (true)
    {
        // 从完成端口获取已完成的I/O操作
        if (!GetQueuedCompletionStatus(g_hCompletionPort,
            &dwBytesTransferred,
            (PULONG_PTR)&pPerHandleData, // 关联的句柄数据（这里是客户端套接字）
            (LPOVERLAPPED*)&pPerIoData, // 关联的OVERLAPPED结构体
            INFINITE)) // 阻塞等待
        {
            // GetQueuedCompletionStatus 返回 FALSE 表示发生错误或完成端口被关闭
            // This check is very important for IO_ACCEPT
            if (pPerHandleData == NULL && pPerIoData->OperationType != IO_ACCEPT)
            {
                {
                    // If pPerHandleData is NULL for a non-ACCEPT operation, it's an error.
                    // This generally means the client connection was already cleaned up,
                    // or there was a problem with the CompletionKey.
                    // For IO_ACCEPT, pPerHandleData IS expected to be NULL (as per current design).
                    std::lock_guard<std::mutex> lock(g_ConsoleMutex);
                    std::cerr << "ERROR: Received completion with NULL pPerHandleData for non-ACCEPT operation. Socket: "
                      << (pPerHandleData ? pPerHandleData->ClientSocket : 0) << " Type: " << pPerIoData->OperationType << std::endl;
                }
                break;
            }

            // 发生错误，通常是客户端连接断开
            if (pPerHandleData && pPerIoData)
            {
                {
                    std::lock_guard<std::mutex> lock(g_ConsoleMutex);
                    std::cerr << "GetQueuedCompletionStatus failed. Error: " << GetLastError() << " for socket: " << pPerHandleData->ClientSocket << std::endl;
                }
                CleanupClient(pPerHandleData->ClientSocket);
                // 释放 PER_IO_DATA
                delete pPerIoData;
            }
            continue;
        }

        // 如果 GetQueuedCompletionStatus 返回 TRUE 且 dwBytesTransferred 为 0，通常表示客户端断开连接
        if (dwBytesTransferred == 0 && (pPerIoData->OperationType == IO_RECV || pPerIoData->OperationType == IO_SEND))
        {
            {
                std::lock_guard<std::mutex> lock(g_ConsoleMutex);
                std::cout << "Client disconnected: " << pPerHandleData->ClientSocket << std::endl;
            }
            CleanupClient(pPerHandleData->ClientSocket);
            delete pPerIoData; // 释放 PER_IO_DATA
            continue;
        }

        // 根据I/O操作类型进行处理
        switch (pPerIoData->OperationType)
        {
        case IO_ACCEPT:
            // For IO_ACCEPT, pPerHandleData IS NULL here, as per your
            // CreateIoCompletionPort for g_ListenSocket.
            // The actual clientSocket is available via pPerIoData->Overlapped's associated socket.
            // We need to pass the *newly accepted client socket* to HandleAccept.
            // This socket is the one that was passed as `lpAcceptSocket` to AcceptEx.
            // AcceptEx's OVERLAPPED structure implicitly holds the socket used in the call.
            // The 'clientSocket' used in the AcceptEx call (in main/HandleAccept recursive call)
            // is effectively 'attached' to the OVERLAPPED in pPerIoData.
            // We need to retrieve it.
            
            HandleAccept(NULL, pPerIoData);
            break;
        case IO_RECV:
            HandleRecv(pPerHandleData, pPerIoData, dwBytesTransferred);
            break;
        case IO_SEND:
            HandleSend(pPerHandleData, pPerIoData, dwBytesTransferred);
            break;
        default:
        {
            std::lock_guard<std::mutex> lock(g_ConsoleMutex);
            std::cerr << "Unknown I/O operation type!" << std::endl;
        }
            // 释放 PER_IO_DATA
            delete pPerIoData;
            break;
        }
    }
}

// 处理 Accept 完成
void HandleAccept(PER_HANDLE_DATA* pPerHandleData, PER_IO_DATA* pPerIoData)
{
    // 获取客户端和本地地址信息
    // The pPerHandleData passed in for IO_ACCEPT will be NULL.
    // We need to get the client socket from the OVERLAPPED structure.
    // The socket for the completed AcceptEx is implicitly linked to the OVERLAPPED.
    // Get the socket from the OVERLAPPED that completed the AcceptEx.
    // This is the tricky part: GetQueuedCompletionStatus for AcceptEx doesn't directly
    // give you the client socket. It gives you the OVERLAPPED. The socket is the
    // one *on which* AcceptEx was called in the first place.
    // So, we need to associate the 'clientSocket' from the AcceptEx call
    // with its PER_IO_DATA if we want to retrieve it here easily,
    // or use a more complex way to get the socket.

    // Better way: The pPerIoData->Overlapped *is* linked to the clientSocket
    // that was passed to AcceptEx. We can retrieve that socket using
    // a Windows API called GetOverlappedResult or simply assume it's the one
    // associated with this pPerIoData.

    // Let's assume the socket on which the AcceptEx was initiated
    // can be extracted. For simplicity, we can temporarily store it in pPerIoData
    // OR we can make it a parameter to HandleAccept.
    // The simplest way to handle this: the clientSocket is implicit to the OVERLAPPED
    // context of the AcceptEx call. But to use it in other functions, we need to store it.

    // *** CRITICAL CORRECTION: ***
    // The `pPerHandleData` that comes into `HandleAccept` for an `IO_ACCEPT` completion
    // will be `NULL` (because you set `CompletionKey` of `g_ListenSocket` to `NULL`).
    // You need to create a `PER_HANDLE_DATA` *here* for the newly accepted client.
    // The client socket for the completed AcceptEx operation *is* the `lpAcceptSocket`
    // that was passed to `lpfnAcceptEx`. We need a way to get it here.
    // A common pattern is to store the `clientSocket` within the `PER_IO_DATA`
    // for `IO_ACCEPT` operations.

    // Let's add SOCKET ClientSocketToAccept to PER_IO_DATA
    // struct PER_IO_DATA
    // {
    //     OVERLAPPED Overlapped;
    //     WSABUF DataBuf;
    //     char Buffer[MAX_BUFFER_SIZE];
    //     IO_OPERATION_TYPE OperationType;
    //     SOCKET ClientSocketToAccept; // <--- ADD THIS
    // };

    // Then, in main when posting AcceptEx:
    // pPerIoData->ClientSocketToAccept = clientSocket;
    // And now, in HandleAccept:
    SOCKET acceptedClientSocket = pPerIoData->ClientSocketToAccept; // Retrieve the socket
    // Validate the client socket
    if (acceptedClientSocket == INVALID_SOCKET)
    {
        std::lock_guard<std::mutex> lock(g_ConsoleMutex);
        std::cerr << "ERROR: Invalid client socket in HandleAccept." << std::endl;
        delete pPerIoData;
        return;
    }

    // Get client and local address information
    sockaddr_in* pLocalAddr = NULL;
    sockaddr_in* pRemoteAddr = NULL;
    int localAddrLen = 0;
    int remoteAddrLen = 0;

    lpfnGetAcceptExSockaddrs(pPerIoData->Buffer,
        0, // AcceptEx 缓冲区中数据长度 (本例为0)
        sizeof(SOCKADDR_STORAGE) + 16,
        sizeof(SOCKADDR_STORAGE) + 16,
        (LPSOCKADDR*)&pLocalAddr, &localAddrLen,
        (LPSOCKADDR*)&pRemoteAddr, &remoteAddrLen);

    // 将新接受的客户端套接字关联到完成端口
    // NOW, CREATE THE PER_HANDLE_DATA FOR THIS NEWLY ACCEPTED CLIENT
    PER_HANDLE_DATA* pNewPerHandleData = new PER_HANDLE_DATA();
    pNewPerHandleData->ClientSocket = acceptedClientSocket;
    // Optionally copy address info if needed, though usually just logging is enough.

    // Associate the *newly created* pNewPerHandleData with the client socket
    if (CreateIoCompletionPort((HANDLE)acceptedClientSocket, g_hCompletionPort, (ULONG_PTR)pNewPerHandleData, 0) == NULL)
    {        
        std::lock_guard<std::mutex> lock(g_ConsoleMutex); // 使用互斥锁保护输出

        std::cerr << "ERROR: CreateIoCompletionPort for client socket " << pNewPerHandleData->ClientSocket << " failed. Error: " << GetLastError() << std::endl;
        closesocket(acceptedClientSocket);
        delete pNewPerHandleData; // 释放新创建的 PER_HANDLE_DATA
        delete pPerIoData; // 释放当前的 PER_IO_DATA
        return;
    }

    // 设置 Accept socket 的 SO_UPDATE_ACCEPT_CONTEXT 选项
    // 这会将监听套接字的属性（如SO_RCVBUF）传递给新接受的套接字
    if (setsockopt(acceptedClientSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&g_ListenSocket, sizeof(g_ListenSocket)) == SOCKET_ERROR)
    {
        std::lock_guard<std::mutex> lock(g_ConsoleMutex);
        std::cerr << "WARNING: setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed for socket " << acceptedClientSocket << ". Error: " << WSAGetLastError() << std::endl;
        // 即使失败，仍然继续，但可能有一些性能问题
    }

    {
        std::lock_guard<std::mutex> lock(g_ConsoleMutex);
        std::cout << "Client connected from: " << inet_ntoa(pRemoteAddr->sin_addr) << ":" << ntohs(pRemoteAddr->sin_port)
            << " Socket: " << acceptedClientSocket << std::endl;
    }
    // 将客户端数据存入 map
    {
        std::lock_guard<std::mutex> lock(g_ClientMapMutex);
        g_ClientMap[acceptedClientSocket].reset(pNewPerHandleData);
    }

    // 投递一个接收请求
    // Post initial Recv using the *newly created* pNewPerHandleData
    PER_IO_DATA* pRecvIoData = new PER_IO_DATA();
    ZeroMemory(&pRecvIoData->Overlapped, sizeof(OVERLAPPED));
    pRecvIoData->OperationType = IO_RECV;
    pRecvIoData->DataBuf.buf = pRecvIoData->Buffer;
    pRecvIoData->DataBuf.len = MAX_BUFFER_SIZE;

    DWORD dwFlags = 0;
    if (WSARecv(acceptedClientSocket, &pRecvIoData->DataBuf, 1, NULL, &dwFlags, &pRecvIoData->Overlapped, NULL) == SOCKET_ERROR)
    {
        if (WSAGetLastError() != ERROR_IO_PENDING)
        {            
            std::lock_guard<std::mutex> lock(g_ConsoleMutex);

            std::cerr << "ERROR: WSARecv failed after accept for socket " << acceptedClientSocket << ". Error: " << WSAGetLastError() << std::endl;
            CleanupClient(acceptedClientSocket);
            delete pRecvIoData;
        }
    }

    // 投递下一个 AcceptEx 请求，以便继续接受新的连接
    PER_IO_DATA* pNextAcceptIoData = new PER_IO_DATA();
    ZeroMemory(&pNextAcceptIoData->Overlapped, sizeof(OVERLAPPED));
    pNextAcceptIoData->OperationType = IO_ACCEPT;
    pNextAcceptIoData->DataBuf.buf = pNextAcceptIoData->Buffer;
    pNextAcceptIoData->DataBuf.len = 0;


    SOCKET nextClientSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);

    if (nextClientSocket == INVALID_SOCKET)
    {
        std::lock_guard<std::mutex> lock(g_ConsoleMutex);
        std::cerr << "WSASocket for next AcceptEx failed. Error: " << WSAGetLastError() << std::endl;
        delete pNextAcceptIoData;
        // 严重错误，可能需要退出或尝试重新创建套接字
    }
    else
    {
        // 创建新的 PER_HANDLE_DATA
        // Store the nextClientSocket in the pNextAcceptIoData so HandleAccept can retrieve it.
        // PER_HANDLE_DATA* pNextPerHandleData = new PER_HANDLE_DATA();
        pNextAcceptIoData->ClientSocketToAccept = nextClientSocket; // <--- Store it here

        DWORD dwBytesReceived = 0;
        ZeroMemory(pNextAcceptIoData->Buffer, sizeof(pNextAcceptIoData->Buffer));

        if (!lpfnAcceptEx(g_ListenSocket, nextClientSocket,
            pNextAcceptIoData->Buffer,
            0,
            sizeof(SOCKADDR_STORAGE) + 16,
            sizeof(SOCKADDR_STORAGE) + 16,
            &dwBytesReceived, &pNextAcceptIoData->Overlapped))
        {
            if (WSAGetLastError() != ERROR_IO_PENDING)
            {
                std::lock_guard<std::mutex> lock(g_ConsoleMutex);
                std::cerr << "AcceptEx failed. Error: " << WSAGetLastError() << std::endl;
                closesocket(nextClientSocket);
                // delete pNextPerHandleData;
                delete pNextAcceptIoData;
            }
        }
    }
    // 释放当前处理完成的 Accept 的 PER_IO_DATA
    delete pPerIoData;
}

// 处理接收完成
void HandleRecv(PER_HANDLE_DATA* pPerHandleData, PER_IO_DATA* pPerIoData, DWORD dwBytesTransferred)
{
    // 假设接收到的数据是文本，直接回显
    pPerIoData->Buffer[dwBytesTransferred] = '\0'; // 添加字符串终止符
    std::cout << "Received " << dwBytesTransferred << " bytes from "
        << pPerHandleData->ClientSocket << ": " << pPerIoData->Buffer << std::endl;

    // 投递一个发送请求（回显数据）
    PER_IO_DATA* pSendIoData = new PER_IO_DATA();
    ZeroMemory(&pSendIoData->Overlapped, sizeof(OVERLAPPED));
    pSendIoData->OperationType = IO_SEND;
    memcpy(pSendIoData->Buffer, pPerIoData->Buffer, dwBytesTransferred); // 复制接收到的数据
    pSendIoData->DataBuf.buf = pSendIoData->Buffer;
    pSendIoData->DataBuf.len = dwBytesTransferred;

    DWORD dwFlags = 0;
    if (WSASend(pPerHandleData->ClientSocket, &pSendIoData->DataBuf, 1, NULL, dwFlags, &pSendIoData->Overlapped, NULL) == SOCKET_ERROR)
    {
        if (WSAGetLastError() != ERROR_IO_PENDING)
        {
            std::cerr << "WSASend failed. Error: " << WSAGetLastError() << std::endl;
            CleanupClient(pPerHandleData->ClientSocket);
            delete pSendIoData;
        }
    }

    // 释放当前的接收 PER_IO_DATA
    delete pPerIoData;
}

// 处理发送完成
void HandleSend(PER_HANDLE_DATA* pPerHandleData, PER_IO_DATA* pPerIoData, DWORD dwBytesTransferred)
{
    std::cout << "Sent " << dwBytesTransferred << " bytes to " << pPerHandleData->ClientSocket << std::endl;

    // 投递下一个接收请求，以便继续接收数据
    PER_IO_DATA* pRecvIoData = new PER_IO_DATA();
    ZeroMemory(&pRecvIoData->Overlapped, sizeof(OVERLAPPED));
    pRecvIoData->OperationType = IO_RECV;
    pRecvIoData->DataBuf.buf = pRecvIoData->Buffer;
    pRecvIoData->DataBuf.len = MAX_BUFFER_SIZE;

    DWORD dwFlags = 0;
    if (WSARecv(pPerHandleData->ClientSocket, &pRecvIoData->DataBuf, 1, NULL, &dwFlags, &pRecvIoData->Overlapped, NULL) == SOCKET_ERROR)
    {
        if (WSAGetLastError() != ERROR_IO_PENDING)
        {
            std::cerr << "WSARecv failed. Error: " << WSAGetLastError() << std::endl;
            CleanupClient(pPerHandleData->ClientSocket);
            delete pRecvIoData;
        }
    }

    // 释放当前的发送 PER_IO_DATA
    delete pPerIoData;
}

// 清理客户端连接
void CleanupClient(SOCKET clientSocket)
{
    std::lock_guard<std::mutex> lock(g_ClientMapMutex);
    auto it = g_ClientMap.find(clientSocket);
    if (it != g_ClientMap.end())
    {
        std::cout << "Cleaning up client: " << clientSocket << std::endl;
        closesocket(it->second->ClientSocket); // 关闭套接字
        g_ClientMap.erase(it); // 从map中移除
        // PER_HANDLE_DATA 会因为 unique_ptr 自动释放
    }
}